home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #2 / Monster Media No. 2 (Monster Media)(1994).ISO / utils2 / vynch_2.zip / VOYNICH.CPP < prev    next >
C/C++ Source or Header  |  1994-06-05  |  57KB  |  1,806 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <conio.h>
  4. #include <string.h>
  5. #include <dos.h>
  6. #include <dir.h>
  7. #include <bios.h>
  8. #include <direct.h>
  9. #include <alloc.h>
  10.  
  11. #define HASH_LEN    4096    /* # hash table entries     */
  12. #define BUFF_LEN   16384    /* size of disk to buffer   */
  13. #define WIPE "VOYNICH ■ VOYNICH ■ VOYNICH ■ VOYNICH ■ VOYNICH ■ VOYNICH ■ "
  14.  
  15. typedef unsigned char uchar;    /*  8 bits, unsigned    */
  16. typedef unsigned int  uint;     /* 16 bits, unsigned    */
  17.  
  18. //===========================================================================
  19. // Globals
  20.  
  21. uchar   *hash_tbl[HASH_LEN];    /* hash table       */
  22. uchar   inbuff[BUFF_LEN];       /* io buffers       */
  23. uchar   outbuff[BUFF_LEN];
  24. int curs = 1;
  25. char crypt[] = ":-(▓@";                 // encryption stamp
  26. extern int _wscroll = 0;                // hold the screen from scrolling
  27. char check[] = "no way in hell are you going to break this cypher!";
  28. char mutate[10000] = "1234567890";
  29. char defaultpth[128];
  30. int defaultdrv;
  31.  
  32. //===========================================================================
  33. // Function prototypes
  34.  
  35. int getkey();
  36. void curon();
  37. void curoff();
  38. void showscrn(int flg);
  39. int oops();
  40. char *wrkfile(int typ, int bkgrdclr, int hghclr, int lowclr, int frclr, int bkclr, int txclr);
  41. int cryptit(char *fname);
  42. int ckencrpt(char*);
  43. int menu(char *fname);
  44. long cnvert(char *code);
  45. void warncrypt(char *fname);
  46. void yikes();
  47. int getcode(int flag, char *code, char *fname);
  48. int getfile(char *temp, int typ, int hghclr, int lowclr, int frclr, int bkclr, int txclr);
  49. void sort(char *ptr[], int fg);
  50. void box(int tr, int br, int ls, int rs, int typ);
  51. int edit(int fg, int lm, char *text);
  52. void menudraw(char *ptr[], int a, int b, int c, int d, int z);
  53. int scrlmenu(char *ptr[], int fg, int a, int b, int c, int d, int typ, int hghclr, int lowclr, int frclr, int bkclr, int txclr);
  54. void menudo(char *ptr[], int a, int b, int c, int d, int z, int count, int hghclr, int lowclr, int bkclr, int txclr);
  55. void cgdrv();
  56. void blank();
  57. void do_compress(char *fname, char *compfle);
  58. void do_decompress(char *fname, char *compfle);
  59. int rdc_compress(uchar *inbuff, uint inbuff_len, uchar *outbuff, uchar *hash_tbl[], uint hash_len);
  60. int rdc_decompress(uchar *inbuff, uint inbuff_len, uchar *outbuff);
  61. void wipefle(char *fname);
  62.  
  63. //===========================================================================
  64. // Function main
  65.  
  66. void main()
  67. {
  68.     int x;
  69.     char buf[128];                    // buffer to store file reads
  70.  
  71.     *(crypt + 3) = 26;
  72.  
  73.      defaultdrv = getdisk();
  74.      strcpy(defaultpth, "X:\\");
  75.      defaultpth[0] = 'A' + getdisk();
  76.      getcurdir(0, defaultpth + 3);
  77.  
  78.     if(strcmp(mutate, "1234567890") == 0)
  79.         x = oops();
  80. //**********************************************************
  81. //*** this is for testing purposes only
  82. //    srand(1956);
  83. //     for(x = 1; x < 10000; x++)
  84. //    {
  85. //        count = random(254) + 1;
  86. //        mutate[x] = count;
  87. //    }
  88. //**********************************************************
  89.  
  90.     while(x)
  91.     {
  92.         strcpy(buf, wrkfile(2, 1, 15, 1, 11, 3, 0));
  93.         if(strlen(buf))
  94.             x = cryptit(buf);
  95.         else
  96.             x = 0;
  97.         if(x == 4)
  98.             x = 0;
  99.     }
  100. window(1, 1, 80, 25);
  101.  
  102. setdisk(defaultdrv);
  103. chdir(defaultpth);
  104. curon();
  105. textcolor(7);
  106. textbackground(0);
  107. clrscr();
  108. }
  109.  
  110. //===========================================================================
  111. //*** function wrkfile: get file and path to work on the integer arguments
  112. //*** are as follows ==> typ:      the box line type
  113. //***                ==> bkgrdclr: the overall screen color
  114. //***                ==> highclr:  the text color of the highlight bar &
  115. //***                              path label
  116. //***                ==> lowclr:   the background color of highlight bar
  117. //***                ==> frclr:    foreground color of box
  118. //***                ==> bkclr:    background color of box
  119. //***                ==> txclr:    color of text inside box
  120.  
  121. char *wrkfile(int typ, int bkgrdclr, int hghclr, int lowclr, int frclr, int bkclr, int txclr)
  122. {
  123.     int x = 1;
  124.     char buf[128];
  125.     char fname[128];
  126.     char *gotptr;
  127.     while(x)                          // for-ever
  128.     {
  129.         *(fname + 0) = NULL;
  130.         window(1, 1, 80, 25);
  131.         showscrn(1);
  132.         window(1, 3, 80, 23);
  133.         textbackground(bkgrdclr);
  134.         clrscr();
  135.         curoff();
  136.         //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  137.         //cprintf("Coreleft is: %lu bytes\n", (unsigned long) coreleft());
  138.         //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  139.         while(x = getfile(fname, typ, hghclr, lowclr, frclr, bkclr, txclr))
  140.             if(x)                   // user picked directory
  141.             {
  142.                 *(buf + 0) = NULL;
  143.                 strcpy(buf, fname);// fname holds new dir
  144.                 chdir(buf);        // change directory
  145.                 textbackground(bkgrdclr);
  146.                 window(1, 1, 80, 25);
  147.                 showscrn(1);
  148.                 window(1, 3, 80, 23);
  149.                 textbackground(bkgrdclr);
  150.                 clrscr();
  151.             }
  152.     }
  153.     curon();
  154.     window(1, 1, 80, 25);
  155.     gotptr = fname;
  156.     return gotptr;
  157. }
  158.  
  159. //===========================================================================
  160. //*** function cryptit: get the job done
  161.  
  162. int cryptit(char *fname)
  163. {
  164.     int x, y, flag;
  165.     char buf;
  166.     char compfle[128];
  167.     char inbuf[BUFSIZ];               // buffer input
  168.     char outbuf[BUFSIZ];              // buffer output
  169.     char *code = new char[6];         // user supplied key
  170.     char *control = new char[6];      // used to check crypt stamp
  171.     char *offptr = new char[6];
  172.     char *passwrd = new char[51];
  173.     long key;                         // derived from code -- seeds srand
  174.     FILE *in, *out;
  175.  
  176.     strcpy(passwrd, check);
  177.     strcpy(compfle, fname);
  178.     if(*(strstr(compfle, ".")) != NULL)
  179.         *(strstr(compfle, ".")) = NULL;
  180.     strcat(compfle, ".$$$");
  181.  
  182.     flag = menu(fname);
  183.     if(flag > 2)
  184.     {
  185.         delete code;
  186.         delete control;
  187.         delete offptr;
  188.         delete passwrd;
  189.         return flag;
  190.     }
  191.     flag = getcode(flag, code, fname);
  192.     if(flag > 2)
  193.     {
  194.         delete code;
  195.         delete control;
  196.         delete offptr;
  197.         delete passwrd;
  198.         return flag;
  199.     }
  200.     key = cnvert(code);
  201.     sprintf(offptr, "%u\0", key);
  202.  
  203.     switch(flag)
  204.     {
  205.         case 2:                      // user selected -- decode file
  206.         gotoxy(57, 13);                   // confirm processing
  207.         cprintf("decoding...");
  208.         in = fopen(fname, "rb");
  209.         setbuf(in, inbuf);
  210.         out = fopen("e$n$c$r$.tmp", "wb");
  211.         setbuf(out, outbuf);
  212.  
  213.         x = 0;
  214.         while(fread(&buf, sizeof(char), 1, in))
  215.         {
  216.             *(control + x) = buf;   // this loop reads in first five
  217.             x++;                    // bytes of file to check and
  218.             if(x == 5)              // make sure that it is encrypted
  219.                 break;             // by this program.
  220.         }
  221.         *(control + x) = NULL;
  222.         if(strcmp(control, crypt) != 0)
  223.         // oops! no encryption stamp!
  224.         {
  225.             fclose(out);
  226.             remove("e$n$c$r$.tmp");
  227.             warncrypt(fname);
  228.             return 3;
  229.         }
  230.         break;
  231.  
  232.         case 1:                      // user selected file encryption
  233.         gotoxy(57, 13);                   // confirm processing
  234.         cprintf("compressing...");
  235.  
  236.         do_compress(fname, compfle);
  237.  
  238.         wipefle(fname);
  239.  
  240.         remove(fname);               // file are the same process -- it
  241.         rename(compfle, fname);      // reverses itself
  242.  
  243.         gotoxy(57, 13);                   // confirm processing
  244.         cprintf("encrypting...  ");
  245.  
  246.         in = fopen(fname, "rb");
  247.         setbuf(in, inbuf);
  248.         out = fopen("e$n$c$r$.tmp", "wb");
  249.         setbuf(out, outbuf);
  250.         fwrite(crypt, sizeof(char), 5, out);    // write encryption stamp
  251.         y = 0;
  252.         for(x = 0; x < 50; x++)
  253.         {
  254.             if(y == 5) y = 0;
  255.             *(passwrd + x) = *(passwrd + x) ^ *(offptr + y);
  256.             y++;
  257.         }
  258.         fwrite(passwrd, sizeof(char), 50, out);
  259.         break;
  260.     }
  261.  
  262. //***********************************************************
  263. //*** encryption/decryption routine
  264.  
  265.     x = 0;
  266.     y = 0;
  267.     if(flag == 2)
  268.     {
  269.         fread(passwrd, sizeof(char), 50, in);
  270.         for(x = 0; x < 50; x++)
  271.         {
  272.             if(y == 5) y = 0;
  273.             *(passwrd + x) = *(passwrd + x) ^ *(offptr + y);
  274.             y++;
  275.         }
  276.         *(passwrd + 50) = NULL;
  277.         if(strcmp(check, passwrd) != 0)
  278.         {
  279.             yikes();
  280.             return 3;
  281.         }
  282.     }
  283.  
  284.     x = 0;
  285.     y = 0;
  286.     while(fread(&buf, sizeof(char), 1, in))
  287.     {
  288.         if(x == 5) x = 0;
  289.         if(y == 10000) y = 0;
  290.         buf = buf ^ (*(mutate + y) ^ *(offptr + x));
  291.         fwrite(&buf, sizeof(char), 1, out);
  292.         y++;
  293.         x++;
  294.     }
  295.     fcloseall();                      // the encryption and decoding of the
  296.  
  297.     wipefle(fname);
  298.     remove(fname);                    // file are the same process -- it
  299.     rename("e$n$c$r$.tmp", fname);    // reverses itself
  300.  
  301.     if(flag == 2)
  302.     {
  303.         gotoxy(57, 13);                   // confirm processing
  304.         cprintf("decompressing...");
  305.         strcpy(compfle, fname);
  306.         if(*(strstr(compfle, ".")) != NULL)
  307.             *(strstr(compfle, ".")) = NULL;
  308.         strcat(compfle, ".$$$");
  309.         do_decompress(fname, compfle);
  310.         fcloseall();                 // the encryption and decoding of the
  311.         remove(fname);               // file are the same process -- it
  312.         rename(compfle, fname);      // reverses itself
  313.     }
  314.  
  315.     delete code;
  316.     delete control;
  317.     delete offptr;
  318.     delete passwrd;
  319.     return 3;
  320. }
  321.  
  322. //===========================================================================
  323. //*** function yikes: this is the wrong passwrd folks
  324.  
  325. void yikes()
  326. {
  327. int x;
  328. char buf = 65;
  329.  
  330. fcloseall();
  331. remove("e$n$c$r$.tmp");
  332. curoff();
  333. putch(7);               // sound bell and abort process
  334. textcolor(11);
  335. textbackground(4);
  336. for(x = 7; x < 14; x++)
  337. {
  338.     gotoxy(15, x);
  339.     cprintf("                                                  ");
  340. }
  341. box(7, 13, 15, 65, 2);
  342. textcolor(14);
  343. gotoxy(17, 9);
  344. cprintf("!! Y I K E S !!");
  345. gotoxy(17, 10);
  346. cprintf("Wrong code! Try again, and good luck.");
  347. gotoxy(17, 11);
  348. cprintf("Press Esc to continue.");
  349.  
  350. while(buf != 27)
  351.     buf = getch();
  352. }
  353.  
  354. //===========================================================================
  355. //*** function ckencrpt: check to see if file is already encrypted
  356.  
  357. int ckencrpt(char* fptr)
  358. {
  359.     FILE *in;
  360.     int x;
  361.     char buf = 66;
  362.     char *control = new char[6];
  363.  
  364.     in = fopen(fptr, "rb");
  365.  
  366.     x = 0;
  367.     while(fread(&buf, sizeof(char), 1, in))
  368.     {
  369.         *(control + x) = buf;        // this loop reads in first five
  370.         x++;                         // bytes of the file
  371.         if(x == 5)
  372.             break;
  373.     }
  374.     fclose(in);
  375.     *(control + x) = NULL;
  376.     if(strcmp(control, crypt) == 0)   // check for match to stamp
  377.     {
  378.         delete control;
  379.         return 1;                    // return true -- file encrypted
  380.     }
  381.     else
  382.     {
  383.         delete control;
  384.         return 0;                    // return false -- file not encrypted
  385.     }
  386. }
  387.  
  388. //===========================================================================
  389. //*** function warncrypt: holler if decode attempt on unencrypted file
  390.  
  391. void warncrypt(char *fname)
  392. {
  393. int x;
  394. char buf = 65;
  395.  
  396. curoff();
  397. putch(7);               // sound bell and abort process
  398. textcolor(11);
  399. textbackground(4);
  400. for(x = 7; x < 14; x++)
  401. {
  402.     gotoxy(15, x);
  403.     cprintf("                                                  ");
  404. }
  405. box(7, 13, 15, 65, 2);
  406. textcolor(14);
  407. gotoxy(17, 9);
  408. cprintf("!! %s", fname);
  409. gotoxy(17, 10);
  410. cprintf("This file was not encrypted by Voynich.");
  411. gotoxy(17, 11);
  412. cprintf("Press Esc to continue.");
  413.  
  414. while(buf != 27)
  415.     buf = getch();
  416. }
  417.  
  418. //===========================================================================
  419. //*** function cnvert: convert user supplied character code to a long
  420.  
  421. long cnvert(char *code)
  422. {
  423.     char buffer[20];
  424.     sprintf(buffer, "%d%d%d%d%d", code[0], code[1], code[2], code[3], code[4]);
  425.     return (atol(buffer));
  426. }
  427.  
  428. //===========================================================================
  429. //*** function wipefle:
  430.  
  431. void wipefle(char *fname)
  432. {
  433.     FILE *in;
  434.     long flbyte;
  435.     struct ffblk ffblk;
  436.  
  437.     findfirst(fname, &ffblk, 0);
  438.     in =  fopen(fname, "r+b");
  439.     for(flbyte = 1; flbyte <=  (ffblk.ff_fsize/sizeof(WIPE)); flbyte++)
  440.         fwrite(WIPE, sizeof(WIPE), 1, in);
  441.     flbyte = ffblk.ff_fsize - (ffblk.ff_fsize/sizeof(WIPE)) * sizeof(WIPE);
  442.     if(flbyte)
  443.         fwrite(WIPE, sizeof(char), flbyte, in);
  444.  
  445.     fclose(in);                 // the encryption and decoding of the
  446. }
  447.  
  448. //===========================================================================
  449. //*** function getcode:
  450.  
  451. int getcode(int flag, char *code, char *fname)
  452. {
  453.     int x;
  454.  
  455.     window(1, 1, 80, 25);
  456.     clrscr();
  457.     showscrn(3);
  458.     window(1, 3, 80, 23);
  459.     textbackground(1);
  460.     clrscr();
  461.  
  462.     window(5, 10, 75, 17);
  463.     textbackground(3);
  464.     clrscr();
  465.     window(1, 3, 80, 23);
  466.     box(8, 16, 5, 75, 2);
  467.     textcolor(4);
  468.     gotoxy(10, 11);
  469.  
  470.     if(flag == 2)
  471.         cprintf("DECODE the file --> %s", fname);
  472.     else
  473.         cprintf("ENCRYPT the file --> %s", fname);
  474.     curon();
  475.     gotoxy(10, 13);
  476.     textcolor(15);
  477.     cprintf("The encryption code must be 5 characters long: ");
  478.     //textcolor(12);
  479.     *(code + 0) = NULL;
  480.  
  481.     x = 1;
  482.     while(x)                          // loop to get user supplied key
  483.     {
  484.         x = edit(5, 5, code);        // call line edit for input
  485.  
  486.         if(x == - 1)                 // user pressed Esc -- abort program
  487.             return 4;
  488.         if(strlen(code) == 5)        // key is proper length
  489.             x = 0;                  // release loop
  490.         else                         // key is too short!
  491.         {
  492.             putch(7);               // warn user and reset
  493.             gotoxy(57, 13);
  494.             cprintf("      ");
  495.             *(code + 0) = NULL;
  496.             gotoxy(57, 13);
  497.         }
  498.     }
  499.     return flag;
  500. }
  501.  
  502. //===========================================================================
  503. //*** function getkey: use DOS interrupt to get keypress values
  504.  
  505. int getkey()
  506. {
  507.     union REGS r;
  508.     r.h.ah = 0;
  509.     return int86(0x16, &r, &r);
  510. }
  511.  
  512. //===========================================================================
  513. //*** function get file: get files in current directory
  514.  
  515. int getfile(char *temp, int typ, int hghclr, int lowclr, int frclr, int bkclr, int txclr)
  516. {
  517.      struct ffblk ffblk;               // structure to hold file data
  518.      int done, z, y = 0, x = 0;        // counters
  519.      char path[128];
  520.      char buffer [25];                 // string to hold selected file name
  521.      char **array = new char *[1000];  // read up to 1000 files in directory
  522.      
  523.      *(buffer + 0) = NULL;
  524.     curoff();
  525.      x = 0;
  526.      done = findfirst("*.*", &ffblk, FA_DIREC);
  527.      // find first file in path
  528.      while(!done)                      // loop to read in rest of files
  529.      {
  530.           if(ffblk.ff_attrib == 16)
  531.           {
  532.                if(strcmp(ffblk.ff_name, ".") != 0)
  533.                {
  534.                     *(array + x) = new char [strlen(ffblk.ff_name) + 2];
  535.                     sprintf(buffer, "\\%s\0", ffblk.ff_name);
  536.                     strcpy(*(array + x), buffer);
  537.                     // put files into array
  538.                }
  539.                else
  540.                     x--;
  541.           }
  542.           else
  543.           {
  544.             //*(array + x) = new char [strlen(ffblk.ff_name) + 13];
  545.                *(array + x) = new char [28];
  546.                sprintf(buffer, "%-12s  %9lu\0", ffblk.ff_name, ffblk.ff_fsize);
  547.                strcpy(*(array + x), buffer);
  548.                // put files into array
  549.           }
  550.           done = findnext(&ffblk);
  551.           x++;
  552.      }
  553.      if(x)
  554.      {
  555.           sort(array, x);              // sort the file list
  556.           
  557.           if(x + 2 < 17)               // dynamically size file display box
  558.                done = x + 3;
  559.           else
  560.                done = 17;
  561.  
  562.           strcpy(path, "X:\\");
  563.           // fill string with form of response: X:\
  564.         path[0] = 'A' + getdisk();   // replace X with current drive letter
  565.           getcurdir(0, path + 3);
  566.           // fill rest of string with current directory
  567.           textcolor(hghclr);
  568.           gotoxy(7, done + 3);
  569.           //printf("heap left: %lu bytes\n", farcoreleft());
  570.           cprintf("Path %c%c%c %s", 196, 196, 16, path);
  571.           gotoxy(41, 3);
  572.           cprintf("%c%c%c select a file to process", 17, 196, 196);
  573.         y = scrlmenu(array, x, 2, done, 2, 35, typ, hghclr, lowclr, frclr, bkclr, txclr);
  574.           // call scroll box and get file
  575.           
  576.           if(y == - 1)                 // user pressed Esc ── abort and exit
  577.           {
  578.                *(temp + 0) = NULL;
  579.                return 0;               // end program
  580.           }
  581.           
  582.           if(y > - 1)
  583.           {
  584.             strcpy(buffer, *(array + y));
  585.                *(strstr(buffer, " ") + 0) = NULL;
  586.             // file to open is in buffer
  587.             if(*(path + strlen(path) - 1) == 92)
  588.                 *(path + strlen(path) - 1) = NULL;
  589.  
  590.             if(*(buffer + 0) == 92)
  591.                 sprintf(temp, "%s%s", path, buffer);
  592.             else
  593.                 sprintf(temp, "%s\\%s", path, buffer);
  594.         }
  595.      }
  596.      else
  597.      {
  598.           blank();
  599.           y = - 2;
  600.      }
  601.      
  602.     for(z = 0; z < x; z++)            // deallocate heap
  603.           delete *(array + z);
  604.      delete array;
  605.      // by temp
  606.      if(y == - 2)                      // need to refresh display
  607.      {
  608.           done = 1;
  609.           *(temp + 0) = NULL;
  610.      }
  611.      else
  612.           if(*(buffer + 0) == 92) done = 1; else done = 0;
  613.      
  614.      return done;
  615. }
  616.  
  617. //===========================================================================
  618. //*** function showscrn: opening screen
  619. void showscrn(int flg)
  620. {
  621.      int x;
  622.     textcolor(11);
  623.     textbackground(3);
  624.     clrscr();
  625.     gotoxy(1, 2);
  626.     cprintf("                           %c%c%c%c  V O Y N I C H  %c%c%c%c", 240, 240, 240, 240, 240, 240, 240, 240);
  627.  
  628.     switch(flg)
  629.     {
  630.         case 1:
  631.         gotoxy(12, 24);
  632.         cprintf("[F10] change drive         %c%c%c%c select         [Esc] quit ", 17, 196, 196, 217);
  633.         break;
  634.         case 2:
  635.         break;
  636.         case 3:
  637.         gotoxy(20, 24);
  638.         cprintf("Type your encryption key and press ENTER");
  639.         break;
  640.     }
  641.     for(x = 1; x < 81; x++)
  642.     {
  643.         gotoxy(x, 1);
  644.         cprintf("%c", 223);
  645.         gotoxy(x, 25);
  646.         cprintf("%c", 220);
  647.     }
  648. }
  649.  
  650. //===========================================================================
  651. //*** function menu:
  652.  
  653. int menu(char *fname)
  654. {
  655.     int x;
  656.     char buf = 66;
  657.  
  658.     textcolor(11);
  659.     gotoxy(1, 24);
  660.     cprintf("                     Press the boxed key to make a selection                ");
  661.     window(1, 3, 80, 23);
  662.     textbackground(1);
  663.     clrscr();
  664.  
  665.     x = ckencrpt(fname);              // check file to see if encrypted
  666.  
  667.     if(x)                             // file is already encrypted
  668.     {
  669.         putch(7);                    // warn the user of existing encoding
  670.         textcolor(11);
  671.         textbackground(4);
  672.         for(x = 13; x < 19; x++)
  673.         {
  674.             gotoxy(52, x);
  675.             cprintf("                         ");
  676.         }
  677.         box(13, 18, 52, 77, 2);
  678.         textcolor(14);
  679.         gotoxy(56, 15);
  680.         cprintf("NOTE! This file is");
  681.         gotoxy(56, 16);
  682.         cprintf("already encrypted.");
  683.     }
  684.  
  685.     textbackground(5);
  686.     textcolor(11);
  687.     gotoxy(10, 3);
  688.     cprintf("       ");
  689.     gotoxy(10, 4);
  690.     cprintf("  <1>  ");
  691.     gotoxy(10, 5);
  692.     cprintf("       ");
  693.     gotoxy(10, 7);
  694.     cprintf("       ");
  695.     gotoxy(10, 8);
  696.     cprintf("  <2>  ");
  697.     gotoxy(10, 9);
  698.     cprintf("       ");
  699.     gotoxy(10, 11);
  700.      cprintf("       ");
  701.      gotoxy(10, 12);
  702.      cprintf("  <3>  ");
  703.      gotoxy(10, 13);
  704.      cprintf("       ");
  705.      gotoxy(10, 15);
  706.      cprintf("       ");
  707.      gotoxy(10, 16);
  708.      cprintf(" <Esc> ");
  709.      gotoxy(10, 17);
  710.      cprintf("       ");
  711.      textbackground(1);
  712.      textcolor(15);
  713.      gotoxy(19, 4);
  714.      cprintf("ENCRYPT the file %s", fname);
  715.      gotoxy(19, 8);
  716.      cprintf("DECODE the file %s", fname);
  717.      gotoxy(19, 12);
  718.      cprintf("OOPS! wrong file, try again.");
  719.      gotoxy(19, 16);
  720.      cprintf("NOPE. just quit.");
  721.      
  722.      curoff();
  723.      // loop to get user menu choice
  724.      while(buf != 49 && buf != 50 && buf != 51 && buf != 27)
  725.           buf = getch();
  726.      switch(buf)
  727.      {
  728.           case 49:                     // user pressed 1 -- encrypt file
  729.           return 1;
  730.           case 50:                     // user pressed 2 -- decode file
  731.           return 2;
  732.           case 51:                     // user pressed 3 -- oops wrong file
  733.           return 3;
  734.           case 27:                     // user pressed Esc -- abort program
  735.           return 4;
  736.     }
  737. return 4;
  738. }
  739.  
  740. //===========================================================================
  741. //*** function blank:
  742.  
  743. void blank()
  744. {
  745.      int x;
  746.      char *stuff = new char[10];
  747.      
  748.      textcolor(11);
  749.      textbackground(3);
  750.      box(10, 16, 40, 76, 2);
  751.      for(x = 11; x < 16; x++)
  752.      {
  753.           gotoxy(41, x);
  754.           cprintf("                                   ");
  755.      }
  756.      textcolor(15);
  757.      gotoxy(42, 12);
  758.      cprintf("Disk is empty.");
  759.      gotoxy(42, 14);
  760.      cprintf("Enter the new drive letter: ");
  761.  
  762.      curon();
  763.      *(stuff + 0) = NULL;
  764.      x = edit(5, 1, stuff);
  765.      curoff();
  766.  
  767.      if(x == 2)
  768.      {
  769.           if(*(stuff + 0) > 96)
  770.                *(stuff + 0) = *(stuff + 0) - 32;
  771.           x = *(stuff + 0);
  772.           x -= 64;
  773.           if(_chdrive(x) == - 1)
  774.                putch(7);
  775.      }
  776.      delete stuff;
  777. }
  778.  
  779. //===========================================================================
  780. //*** Function sort: a standard shell sort algorithm. array is pointer array
  781. //*** to strings, fg is the count.
  782. //*** NOTE! strings in the array better be null terminated!
  783.  
  784. void sort(char *ptr[], int fg)
  785. {
  786.      int x = 2;
  787.      int y = fg;
  788.      int z;
  789.      int t;
  790.      int done;
  791.      char *temp1;
  792.      
  793.      x = fg / 2;
  794.      while(x >= 1)
  795.      {
  796.           for(y = 0; y < x; y++)
  797.           {
  798.                for(z = y; z < (fg - x); z += x)
  799.                {
  800.                     t = z;
  801.                     temp1 = *(ptr + (z + x));
  802.                     done = 0;
  803.                     while(t >= y && done == 0)
  804.                     {
  805.                          if(strcmp(temp1, *(ptr + t)) > 0)
  806.                               done = 1;
  807.                          else
  808.                          {
  809.                               *(ptr + (t + x)) = *(ptr + t);
  810.                               t -= x;
  811.                          }
  812.                     }
  813.                     *(ptr + (t + x)) = temp1;
  814.                }
  815.           }
  816.           x = x / 2;
  817.      }
  818. }
  819.  
  820. //===========================================================================
  821. //*** function box: draw a double line box on the screen
  822. //*** the four intergers are the coordinates of the four corners.
  823. //*** tr = top row ── br = bottom row ── ls = left side ── rs = right side
  824.  
  825. void box(int tr, int br, int ls, int rs, int typ)
  826. {
  827.      int x;
  828.      unsigned char lftop;
  829.      unsigned char rgtop;
  830.      unsigned char lfbtm;
  831.      unsigned char rgbtm;
  832.      unsigned char hzlin;
  833.      unsigned char vtlin;
  834.      
  835.      switch(typ)
  836.      {
  837.           case 1:                      // double line box
  838.           lftop = 201;
  839.           rgtop = 187;
  840.           lfbtm = 200;
  841.           rgbtm = 188;
  842.           hzlin = 205;
  843.           vtlin = 186;
  844.           break;
  845.           case 2:
  846.           lftop = 218;
  847.           rgtop = 191;
  848.           lfbtm = 192;
  849.           rgbtm = 217;
  850.           hzlin = 196;
  851.           vtlin = 179;
  852.           break;
  853.           case 3:
  854.           lftop = 214;
  855.           rgtop = 183;
  856.           lfbtm = 211;
  857.           rgbtm = 189;
  858.           hzlin = 196;
  859.           vtlin = 186;
  860.           break;
  861.           case 4:
  862.           lftop = 213;
  863.           rgtop = 184;
  864.           lfbtm = 212;
  865.           rgbtm = 190;
  866.           hzlin = 205;
  867.           vtlin = 179;
  868.           break;
  869.      }
  870.      gotoxy(ls, tr);                   // draw in the box corners
  871.      cprintf("%c", lftop);
  872.      gotoxy(rs, tr);
  873.      cprintf("%c", rgtop);
  874.      gotoxy(ls, br);
  875.      cprintf("%c", lfbtm);
  876.      gotoxy(rs, br);
  877.      cprintf("%c", rgbtm);
  878.      
  879.      for(x = tr + 1; x <= br - 1; x++) // loop to draw in box sides
  880.      {
  881.           gotoxy(ls, x);
  882.           cprintf("%c", vtlin);
  883.           gotoxy(rs, x);
  884.           cprintf("%c", vtlin);
  885.      }
  886.      
  887.      for(x = ls + 1; x <= rs - 1; x++) // loop to draw in box top & bottom
  888.      {
  889.           gotoxy(x, tr);
  890.           cprintf("%c", hzlin);
  891.           gotoxy(x, br);
  892.           cprintf("%c", hzlin);
  893.      }
  894.      textcolor(0);
  895.      for(x = tr + 1; x <= br; x++)     // loop to draw in box shadow
  896.      {
  897.           gotoxy(rs + 1, x);
  898.           cprintf("%c", 219);
  899.      }
  900.      
  901.      for(x = ls + 1; x <= rs + 1; x++) // loop to draw in box shadow
  902.      {
  903.           gotoxy(x, br + 1);
  904.           cprintf("%c", 219);
  905.      }
  906. }
  907.  
  908. //===========================================================================
  909. //*** function edit: a single line text input function using three parameters.
  910. //*** the variable fg can be used to both control the function when called as
  911. //*** well as return a value for subsequent action. The variable lm sets the
  912. //*** allowable length of the input string. The string text will display in the
  913. //*** input field upon call as well as return the user's input data. (!! text
  914. //*** is a pointer to a string.) This function requires the function getkey()
  915.  
  916. int edit(int fg, int lm, char *text)
  917. {
  918.      int r;                            // anchored cursor position
  919.      int q;                            // limit counter
  920.      int z;                            // use as for loop counter
  921.      int x;                            // cursor position
  922.      int y;                            // cursor position
  923.      int flg;                          // internal string position
  924.      int code = 1;                     // scan code flag
  925.      char kbd;                         // key press value
  926.      char temp[45];                    // temporary string buffer
  927.      int pd = 1;                       // initialize loop control variables
  928.      int ins = 1;                      // default with Ins on
  929.      union scan                        // union to hold keyboard scan code
  930.      {
  931.           int c;
  932.           char ch[2];
  933.      } sc;
  934.      
  935.      r = wherex();                     // constant for left cursor position
  936.      q = strlen(text);                 // set limit counter from string sent
  937.      cprintf("%s", text);              // display any sent text
  938.      x = wherex();                     // get the current cursor position
  939.      y = wherey();
  940.      
  941.      do                                // main loop -- take input until exit
  942.      {
  943.           gotoxy(x, y);
  944.           while(kbhit() == 0);         // holding loop waits for key press
  945.           
  946.           sc.c = getkey();             // get the keyboard scan code
  947.           if(*(sc.ch + 0) == 0)        // this is a function or cursor key
  948.           {
  949.                code = 0;               // set scan code flag
  950.                kbd = *(sc.ch + 1);     // read in key press value
  951.           }
  952.           else                         // this is an alphanumeric key
  953.           {
  954.                code = 1;               // set scan code flag
  955.                kbd = *(sc.ch + 0);     // read in key press value
  956.           }
  957.           
  958.           if(code)                     // key is alpha-numeric or ESC/CR
  959.           {
  960.                switch(kbd)
  961.                {
  962.                     case 27:           // user pressed ESC
  963.                     pd = 0;            // release loop
  964.                     fg = - 1;          // set return flag
  965.                     break;
  966.                     
  967.                     case 13:           // user pressed Enter
  968.                     pd = 0;            // release loop
  969.                     fg = 2;            // set return flag
  970.                     break;
  971.                     
  972.                     case 8:            // user pressed bkspace
  973.                     if(x > r)          // bkspace is valid
  974.                     {
  975.                          if(x < r + q) // !! in middle of string
  976.                          {
  977.                               code = (r + q) - x;
  978.                               // get position in string
  979.                               pd = 0;  // read string from cursor
  980.                               for(z = (q - code); z != q; z++)
  981.                                    // to end & store
  982.                               {
  983.                                    flg = *(text + z);
  984.                                    // in temp string
  985.                                    *(temp + pd) = flg;
  986.                                    ++pd;
  987.                               }
  988.                               
  989.                               *(temp + pd) = '\0';
  990.                               *(text + (q - code) - 1) = NULL;
  991.                               // remove end chr
  992.                               strcat(text, temp);
  993.                               // re-attach string end
  994.                               gotoxy(--x, y);
  995.                               cprintf("%s%c", temp, 32);
  996.                               // redraw screen
  997.                               --q;     // decrement strlen counter
  998.                               pd = 1;  // put pd back after use!
  999.                          }
  1000.                          else          // at end of the string
  1001.                          {
  1002.                               putch(8);// take care of display
  1003.                               putch(32);
  1004.                               putch(8);
  1005.                               *(text + strlen(text) - 1) = NULL;
  1006.                               // truncate string
  1007.                               --q;     // decrement strlen counter
  1008.                               --x;     // decrement cur positon
  1009.                          }
  1010.                     }
  1011.                     break;
  1012.                     
  1013.                     default:           // valid key press
  1014.                     if(x < r + q)      // !! middle of string
  1015.                     {
  1016.                          if(ins)       // Ins mode is on
  1017.                          {
  1018.                               if(q < lm)
  1019.                                    // limit is not reached
  1020.                               {
  1021.                                    code = (r + q) - x;
  1022.                                    pd = 0;
  1023.                                    for(z = (q - code); z != q; ++z)
  1024.                                    {
  1025.                                         flg = *(text + z);
  1026.                                         *(temp + pd) = flg;
  1027.                                         ++pd;
  1028.                                    }
  1029.                                    *(temp + pd) = '\0';
  1030.                                    // see bkspace
  1031.                                    *(text + (q - code)) = kbd;
  1032.                                    // process for
  1033.                                    *(text + (q - code) + 1) = '\0';
  1034.                                    // notes on this
  1035.                                    strcat(text, temp);
  1036.                                    // section
  1037.                                    putch(kbd);
  1038.                                    cprintf("%s", temp);
  1039.                                    pd = 1;
  1040.                                    ++q;
  1041.                                    ++x;
  1042.                               }
  1043.                          }
  1044.                          else          // Ins mode is off
  1045.                          {
  1046.                               code = (r + q) - x;
  1047.                               pd = 0;
  1048.                               for(z = (q - code + 1); z != q; ++z)
  1049.                               {
  1050.                                    flg = *(text + z);
  1051.                                    *(temp + pd) = flg;
  1052.                                    ++pd;
  1053.                               }        // see bkspace process
  1054.                               *(temp + pd) = '\0';
  1055.                               // for notes
  1056.                               *(text + (q - code)) = kbd;
  1057.                               *(text + (q - code) + 1) = '\0';
  1058.                               strcat(text, temp);
  1059.                               putch(kbd);
  1060.                               pd = 1;
  1061.                               ++x;
  1062.                          }
  1063.                     }
  1064.                     else               // at end of string
  1065.                     {
  1066.                          if(q < lm)
  1067.                          {
  1068.                               putch(kbd);
  1069.                               sprintf(temp, "%s%c", text, kbd);
  1070.                               // here's another
  1071.                               strcpy(text, temp);
  1072.                               // way to splice
  1073.                               ++q;     // the ends of two
  1074.                               ++x;     // strings
  1075.                          }
  1076.                     }
  1077.                }
  1078.           }
  1079.           else                         // function or cursor control key
  1080.           {
  1081.                switch(kbd)
  1082.                {
  1083.                     case 82:           // user toggled Ins
  1084.                     if(ins)            // set Ins flag as indicated
  1085.                          ins = 0;      // if on, turn off
  1086.                     else
  1087.                          ins = 1;      // if off, turn on
  1088.                     break;
  1089.                     case 72:           // user pressed up arrow
  1090.                     if(fg < 5)
  1091.                     {
  1092.                          fg = 1;       // set return flag
  1093.                          pd = 0;       // release loop
  1094.                     }
  1095.                     break;
  1096.                     case 80:           // user pressed down arrow
  1097.                     if(fg < 5)
  1098.                     {
  1099.                          fg = 2;       // set return flag
  1100.                          pd = 0;       // release loop
  1101.                     }
  1102.                     break;
  1103.                     case 75:           // user pressed left arrow
  1104.                     if(x > r)          // key press is valid so
  1105.                          --x;          // decrement cursor counter
  1106.                     break;
  1107.                     case 77:           // user pressed right arrow
  1108.                     if(x < r + q)      // key press is valid
  1109.                          ++x;          // increment cursor counter
  1110.                     break;
  1111.                     case 71:           // user pressed home
  1112.                     x = r;             // reset cursor counter
  1113.                     break;
  1114.                     case 79:           // user pressed end
  1115.                     x = r + strlen(text);
  1116.                     // reset cursor counter
  1117.                     break;
  1118.                     case 83:           // user pressed del
  1119.                     if(x < r + q)      // key press is valid
  1120.                     {
  1121.                          code = (r + q) - x;
  1122.                          pd = 0;
  1123.                          for(z = (q - code + 1); z != q; ++z)
  1124.                          {
  1125.                               flg = *(text + z);
  1126.                               *(temp + pd) = flg;
  1127.                               ++pd;
  1128.                          }             // see bkspace process for
  1129.                          *(temp + pd) = '\0';
  1130.                          // notes on this routine
  1131.                          *(text + (q - code)) = '\0';
  1132.                          strcat(text, temp);
  1133.                          cprintf("%s%c", temp, 32);
  1134.                          pd = 1;
  1135.                          --q;
  1136.                     }
  1137.                     break;
  1138.                     case 68:           // user pressed [F10]
  1139.                     if(fg < 5)
  1140.                     {
  1141.                          fg = 3;
  1142.                          pd = 0;
  1143.                     }
  1144.                }
  1145.           }
  1146.           
  1147.      } while(pd != 0);
  1148.      return fg;                        // set return flag
  1149. }
  1150.  
  1151. //===========================================================================
  1152. //*** function scrlmenu: draws a box on screen, displays the menu selections,
  1153. //*** and allows the user to scroll through and make a selection. the var
  1154. //*** fg is the number of items in the array and the vars a thru d are the
  1155. //*** screen coordinates for the menu box. This function calls the functions
  1156. //*** getkey(), curon(), curoff(), menudo(), and menudraw()
  1157.  
  1158. int scrlmenu(char *ptr[], int fg, int a, int b, int c, int d, int typ, int hghclr, int lowclr, int frclr, int bkclr, int txclr)
  1159. {
  1160.      int pd;                           // loop control flag
  1161.      char kbd;                         // user keypress
  1162.      int z = 0;                        // offset counter
  1163.      int count = 0;                    // menu counter
  1164.     int code = 0;                     // keyboard scan code
  1165.      int util;                         // utilities choice
  1166.      char buffer[60];                  // hold system command line
  1167.      union scan                        // union to hold keyboard scan code
  1168.      {
  1169.           int c;
  1170.           char ch[2];
  1171.      } sc;
  1172.      
  1173.      curoff();                         // turn cursor off
  1174.      textcolor(frclr);
  1175.      textbackground(bkclr);
  1176.      box(a, b, c, d, typ);             // draw a box for the menu
  1177.      textcolor(0);
  1178.      menudraw(ptr, a, b, c, d, z);     // draw the menu items
  1179.      menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1180.      
  1181.      pd = 1;                           // loop control flag
  1182.      while(pd)                         // loop allows user to move selection
  1183.      {
  1184.         while(kbhit() == 0);         // holding loop waits for key press
  1185.           
  1186.           sc.c = getkey();             // get the keyboard scan code
  1187.           if(*(sc.ch + 0) == 0)        // this is a function or cursor key
  1188.           {
  1189.                code = 1;               // set scan code flag
  1190.                kbd = *(sc.ch + 1);     // read in key press value
  1191.           }
  1192.           else                         // this is an alphanumeric key
  1193.           {
  1194.                code = 0;               // set scan code flag
  1195.                kbd = *(sc.ch + 0);     // read in key press value
  1196.           }
  1197.           
  1198.           if(code)                     // user pressed non-alpha key
  1199.           {
  1200.                switch(kbd)
  1201.                {
  1202.                     case 72:           // user pressed up arrow
  1203.                     --count;           // decrement menu counter
  1204.                 if(count < 0)      // already at top
  1205.                     {
  1206.                          count = fg - 1;
  1207.                          // roll over to bottom
  1208.                          if(fg > (b - a) - 1)
  1209.                               // this mess allows
  1210.                          {
  1211.                               // for the possibility
  1212.                               if(fg >= (b - a - 1) * 2)
  1213.                               {
  1214.                                    z = (b - a - 1);
  1215.                                    // that the menu items
  1216.                                    z += (fg - (z * 2));
  1217.                                    // number more or less
  1218.                               }        // than will fit box
  1219.                               else
  1220.                                    z = fg - (b - a - 1);
  1221.                          }
  1222.                          else
  1223.                               z = 0;
  1224.                     menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1225.                          // place highlight
  1226.                     }
  1227.                     else               // not yet at top so move up one
  1228.                     {
  1229.                          if(wherey() == a + 1)
  1230.                               z -= 1;
  1231.                          if(z < 0)
  1232.                               z = 0;
  1233.                          menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1234.                          // place highlight
  1235.                     }
  1236.                     break;
  1237.                     case 80:           // user pressed down arrow
  1238.                     ++count;           // increment menu counter
  1239.                     if(count == fg)    // already at bottom of list
  1240.                     {
  1241.                          count = 0;    // roll over to top
  1242.                          z = 0;
  1243.                          menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1244.                     // place highlight
  1245.                 }
  1246.                 else               // not yet at bottom of list
  1247.                 {
  1248.                     if(wherey() == b - 1)
  1249.                         z += 1;
  1250.                     menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1251.                     // place highlight
  1252.                 }
  1253.                 break;
  1254.                 //case 67:
  1255.                 //return - 2;
  1256.                     case 68:
  1257.                     cgdrv();
  1258.                     return - 2;
  1259.                }
  1260.           }
  1261.           else                         // user pressed alph-numeric
  1262.                switch(kbd)
  1263.                {
  1264.                     case 13:           // user pressed Enter
  1265.                     if(ptr[count][0] == 4)
  1266.                     {
  1267.                          for(util = 0; util < strlen(*(ptr + count)) - 2; util++)
  1268.                               ptr[count][util] = ptr[count][util + 2];
  1269.                          ptr[count][util] = NULL;
  1270.                     }
  1271.                     pd = 0;            // set exit
  1272.                     break;
  1273.                     case 27:           // user pressed Esc
  1274.                     pd = 0;            // set loop control to exit
  1275.                     fg = - 1;          // set return flag to abort
  1276.                     break;
  1277.                     case 32:
  1278.                     if(c == 35)
  1279.                          break;
  1280.                     if(ptr[count][0] == 4)
  1281.                     {
  1282.                          for(util = 0; util < strlen(*(ptr + count)) - 2; util++)
  1283.                               ptr[count][util] = ptr[count][util + 2];
  1284.                          ptr[count][util] = NULL;
  1285.                     }
  1286.                     else
  1287.                     {
  1288.                          if(*(ptr + count)[0] != 92)
  1289.                          {
  1290.                               sprintf(buffer, "%c %s", 4, *(ptr + count));
  1291.                               strcpy(*(ptr + count), buffer);
  1292.                          }
  1293.                          else
  1294.                               putch(7);
  1295.                     }
  1296.                     gotoxy(7, wherey());
  1297.                     textcolor(15);     // set highlight bar color
  1298.                     textbackground(7);
  1299.                     cprintf("   %s", *(ptr + count));
  1300.                     textcolor(7);      // put color back
  1301.                     textbackground(0);
  1302.                     
  1303.                     ++count;           // increment menu counter
  1304.                     if(count == fg)    // already at bottom of list
  1305.                     {
  1306.                          count = 0;    // roll over to top
  1307.                          z = 0;
  1308.                          menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1309.                          // place highlight
  1310.                     }
  1311.                     else               // not yet at bottom of list
  1312.                     {
  1313.                          if(wherey() == b - 1)
  1314.                               z += 1;
  1315.                          menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1316.                          // place highlight
  1317.                     }
  1318.                     break;
  1319.                     default:           // process any alpha key to scroll box
  1320.                     if(kbd > 96)
  1321.                          kbd = kbd - 32;
  1322.                     // all lower case
  1323.                     for(code = 0; code <= fg; code++)
  1324.                          // loop through array
  1325.                     {
  1326.                          if(kbd == ptr[code][0])
  1327.                               // find first element
  1328.                          {
  1329.                               // where first letter
  1330.                               count = code;
  1331.                               // matches keypress
  1332.                               if(count > (b - a) - 2)
  1333.                                    z = count - ((b - a) - 2);
  1334.                               else
  1335.                                    z = 0;
  1336.                               menudo(ptr, a, b, c, d, z, count, hghclr, lowclr, bkclr, txclr);
  1337.                               // place mark
  1338.                               break;
  1339.                          }
  1340.                     }
  1341.                     break;
  1342.                }
  1343.      }
  1344.      
  1345.      if(fg > - 1)
  1346.           fg = count;                  // set return flag
  1347.      
  1348.      //curon();
  1349.      return fg;                        // return user selection
  1350. }
  1351.  
  1352. //===========================================================================
  1353. //*** function menudraw: draws the items inside the menu box
  1354.  
  1355. void menudraw(char *ptr[], int a, int b, int c, int d, int z)
  1356. {
  1357.      char temp[81];
  1358.      int offset;
  1359.      int q;
  1360.      int x;
  1361.      
  1362.      for(x = z; x != z + ((b - a) - 1); ++x)
  1363.           // loop to draw in menu items
  1364.      {
  1365.           offset = (d - c - 5 - strlen(*(ptr + x)));
  1366.           
  1367.           for(q = 0; q != offset; ++q) // loop to load temp with blanks
  1368.                *(temp + q) = 32;       // temp fills in the balance of
  1369.           *(temp + q) = '\0';          // the box with spaces
  1370.           
  1371.           gotoxy(c + 1, (a + 1) + x - z);
  1372.           cprintf("    %s%s", *(ptr + x), temp);
  1373.      }
  1374. }
  1375.  
  1376. //===========================================================================
  1377. //*** function menudo places the highlight on the menu selection
  1378.  
  1379. void menudo(char *ptr[], int a, int b, int c, int d, int z, int count, int hghclr, int lowclr, int bkclr, int txclr)
  1380. {
  1381.      char temp[81];
  1382.      int x;
  1383.      int offset = (d - c - 5 - strlen(*(ptr + count)));
  1384.      
  1385.      menudraw(ptr, a, b, c, d, z);     // 1st re-draw menu items
  1386.      
  1387.      for(x = 0; x != offset; ++x)      // loop to load temp with blanks
  1388.           *(temp + x) = 32;
  1389.      *(temp + x) = '\0';
  1390.      
  1391.      textcolor(hghclr);                // set highlight bar color
  1392.      textbackground(lowclr);
  1393.      gotoxy(c + 1, (a + 1) + count - z);
  1394.      // draw highlighted choice
  1395.      cprintf("    %s%s", *(ptr + count), temp);
  1396.      textcolor(txclr);                 // put color back
  1397.      textbackground(bkclr);
  1398. }
  1399.  
  1400. //===========================================================================
  1401. //*** function cgdrv:
  1402.  
  1403. void cgdrv()
  1404. {
  1405.      int x;
  1406.      char *stuff = new char[10];
  1407.      
  1408.      textcolor(11);
  1409.      textbackground(3);
  1410.      box(11, 15, 40, 75, 2);
  1411.      for(x = 12; x < 15; x++)
  1412.      {
  1413.           gotoxy(41, x);
  1414.           cprintf("                                  ");
  1415.      }
  1416.      textcolor(15);
  1417.      gotoxy(42, 13);
  1418.      cprintf("Enter the new drive letter: ");
  1419.      
  1420.      curon();
  1421.      *(stuff + 0) = NULL;
  1422.      x = edit(5, 1, stuff);
  1423.      curoff();
  1424.      
  1425.      if(x == 2)
  1426.      {
  1427.           if(*(stuff + 0) > 96)
  1428.                *(stuff + 0) = *(stuff + 0) - 32;
  1429.           x = *(stuff + 0);
  1430.           x -= 64;
  1431.           if(_chdrive(x) == - 1)
  1432.                putch(7);
  1433.      }
  1434.      
  1435.      textbackground(7);
  1436.      for(x = 9; x < 16; x++)
  1437.      {
  1438.           gotoxy(38, x);
  1439.           cprintf("                                         ");
  1440.     }
  1441.      textcolor(7);
  1442.      textbackground(0);
  1443.      delete stuff;
  1444. }
  1445.  
  1446. //===========================================================================
  1447. //*** function cursor off: turns the damn cursor off!
  1448.  
  1449. void curoff()
  1450. {
  1451.      static union REGS inregs, outregs;
  1452.     if(curs)
  1453.      {
  1454.           inregs.h.ah = 1;             // load registers
  1455.           inregs.h.ch = 0x20;
  1456.           inregs.h.cl = 0;
  1457.           int86(0x10, &inregs, &outregs);
  1458.           // DOS call turns cursor off
  1459.           curs = 0;                    // set cursor flag
  1460.      }
  1461. }
  1462.  
  1463. //===========================================================================
  1464. //*** function cursor on: turns the cursor back on
  1465.  
  1466. void curon()
  1467. {
  1468.     static union REGS inregs, outregs;
  1469.      if(!curs)
  1470.      {
  1471.           inregs.h.ah = 1;             // load registers
  1472.         inregs.h.ch = 6;             // !! will need to adjust this to
  1473.           inregs.h.cl = 7;             // handle color and mono monitors !!
  1474.         int86(0x10, &inregs, &outregs);
  1475.           // DOS call turn cursor on
  1476.           curs = 1;                    // set cursor flag
  1477.     }
  1478. }
  1479.  
  1480. //==========================================================================
  1481. //*** function oops: not installed! default out
  1482.  
  1483. int oops()
  1484. {
  1485. char buf;
  1486.     putch(7);
  1487.     showscrn(2);
  1488.     window(1, 3, 80, 23);
  1489.     textcolor(15);
  1490.     textbackground(1);
  1491.     curoff();
  1492.     clrscr();
  1493.     window(5, 5, 75, 20);
  1494.     cprintf("N O T E:\r\n");
  1495.     cprintf("~~~~~~~~\r\n\n");
  1496.     cprintf("This copy of Voynich has not been initialized. Until you run the\r\n");
  1497.     cprintf("initialization program, Voynich will default to this screen and then\r\n");
  1498.     cprintf("exit.\r\n\n");
  1499.     cprintf("Before you initialize Voynich, read through the file README!.NOW.\r\n");
  1500.     cprintf("If you ignore the information in the README!.NOW file, you could\r\n");
  1501.     cprintf("make a costly mistake.\r\n\n");
  1502.     textcolor(14);
  1503.     cprintf("Press Esc to exit to DOS.");
  1504.  
  1505.     while(buf != 27)
  1506.         buf = getch();
  1507. return 0;
  1508. }
  1509.  
  1510. void do_compress(char *fname, char *compfle)
  1511. {
  1512.     int bytes_read;
  1513.     int compress_len;
  1514.     FILE *infile, *outfile;
  1515.  
  1516.     infile = fopen(fname, "rb");
  1517.     outfile = fopen(compfle, "wb");
  1518.  
  1519.     /* read infile BUFF_LEN bytes at a time */
  1520.     while((bytes_read = fread(inbuff, 1, BUFF_LEN, infile)) > 0)
  1521.     {
  1522.         /* compress this load of bytes */
  1523.         compress_len = rdc_compress(inbuff, bytes_read, outbuff, hash_tbl, HASH_LEN);
  1524.         /* write length of compressed buffer */
  1525.         if(fwrite(&compress_len, sizeof(int), 1, outfile) != 1)
  1526.             exit(1);
  1527.         /* check for negative length indicating the
  1528.         buffer could not be compressed  */
  1529.         if(compress_len < 0)
  1530.             compress_len = 0 - compress_len;
  1531.         /* write the buffer */
  1532.         if(fwrite(outbuff, compress_len, 1, outfile) != 1)
  1533.             exit(1);
  1534.         /* we're done if less than full buffer was read */
  1535.         if(bytes_read != BUFF_LEN)
  1536.             break;
  1537.     }
  1538.  
  1539.     /* add trailer to indicate end of file */
  1540.     compress_len = 0;
  1541.     if(fwrite(&compress_len, sizeof(int), 1, outfile) != 1)
  1542.         exit(1);
  1543.     fcloseall();
  1544. }
  1545.  
  1546. void do_decompress(char *fname, char *compfle)
  1547. {
  1548.     int block_len;
  1549.     int decomp_len;
  1550.     FILE *infile, *outfile;
  1551.  
  1552.     infile = fopen(fname, "rb");
  1553.     outfile = fopen(compfle, "wb");
  1554.  
  1555.     /* read infile BUFF_LEN bytes at a time */
  1556.     for(;;)
  1557.     {
  1558.         if(fread(&block_len, sizeof(int), 1, infile) != 1)
  1559.             exit(1);
  1560.         /* check for end-of-file flag */
  1561.         if(block_len == 0)
  1562.             return;
  1563.         if(block_len < 0)            /* copy uncompressed chars */
  1564.         {
  1565.             decomp_len = 0 - block_len;
  1566.             if(fread(outbuff, decomp_len, 1, infile) != 1)
  1567.                 exit(1);
  1568.         }
  1569.         else                         /* decompress this buffer */
  1570.         {
  1571.             if(fread(inbuff, block_len, 1, infile) != 1)
  1572.                 exit(1);
  1573.             decomp_len = rdc_decompress(inbuff, block_len,
  1574.                 outbuff);
  1575.         }
  1576.         /* and write this buffer outfile */
  1577.         if(fwrite(outbuff, decomp_len, 1, outfile) != 1)
  1578.             exit(1);
  1579.     }
  1580. }
  1581.  
  1582. /*                                                 from C Users Journal 10/92
  1583.  * COMPRS.C - Ross Data Compression (RDC)
  1584.  *            compress function
  1585.  *
  1586.  * Written by Ed Ross, 1/92
  1587.  *
  1588.  * compress inbuf_len bytes of inbuff into outbuff
  1589.  * using hash_len entries in hash_tbl.
  1590.  *
  1591.  * return length of outbuff, or "0 - inbuff_len"
  1592.  * if inbuff could not be compressed.               */
  1593.  
  1594. //#include <string.h>
  1595.  
  1596. typedef unsigned char uchar;        /* 8 bits, unsigned */
  1597. typedef unsigned int uint;          /* 16 bits, unsigned */
  1598.  
  1599. int rdc_compress(uchar *inbuff, uint inbuff_len, uchar *outbuff, uchar *hash_tbl[], uint hash_len)
  1600. {
  1601.     uchar   *in_idx = inbuff;
  1602.     uchar   *inbuff_end = inbuff + inbuff_len;
  1603.     uchar   *anchor;
  1604.     uchar   *pat_idx;
  1605.     uint    cnt;
  1606.     uint    gap;
  1607.     uint    c;
  1608.     uint    hash;
  1609.     uint    *ctrl_idx = (uint *) outbuff;
  1610.     uint    ctrl_bits;
  1611.     uint    ctrl_cnt = 0;
  1612.  
  1613.     uchar   *out_idx = outbuff + sizeof(uint);
  1614.     uchar   *outbuff_end = outbuff + (inbuff_len - 48);
  1615.  
  1616.     /* skip the compression for a small buffer */
  1617.  
  1618.     if(inbuff_len <= 18)
  1619.     {
  1620.         memcpy(outbuff, inbuff, inbuff_len);
  1621.         return 0 - inbuff_len;
  1622.     }
  1623.  
  1624.     /* adjust # hash entries so hash algorithm can
  1625.     use 'and' instead of 'mod'       */
  1626.     hash_len--;
  1627.  
  1628.     /* scan thru inbuff */
  1629.     while(in_idx < inbuff_end)
  1630.     {
  1631.         /* make room for the control bits
  1632.         and check for outbuff overflow */
  1633.         if(ctrl_cnt++ == 16)
  1634.         {
  1635.             *ctrl_idx = ctrl_bits;
  1636.             ctrl_cnt = 1;
  1637.             ctrl_idx = (uint *) out_idx;
  1638.             out_idx += 2;
  1639.  
  1640.             if(out_idx > outbuff_end)
  1641.             {
  1642.                 memcpy(outbuff, inbuff, inbuff_len);
  1643.                 return 0 - inbuff_len;
  1644.             }
  1645.         }
  1646.  
  1647.         /* look for rle  */
  1648.         anchor = in_idx;
  1649.         c = *in_idx++;
  1650.         while(in_idx < inbuff_end
  1651.                 && *in_idx == c
  1652.                 && (in_idx - anchor) < 4114)
  1653.             in_idx++;
  1654.         /* store compression code if character is
  1655.         repeated more than 2 times  */
  1656.         if((cnt = in_idx - anchor) > 2)
  1657.         {
  1658.             if(cnt <= 18)           /* short rle */
  1659.             {
  1660.                 *out_idx++ = cnt - 3;
  1661.                 *out_idx++ = c;
  1662.             }
  1663.             else                    /* long rle */
  1664.             {
  1665.                 cnt -= 19;
  1666.                 *out_idx++ = 16 + (cnt & 0x0F);
  1667.                 *out_idx++ = cnt >> 4;
  1668.                 *out_idx++ = c;
  1669.             }
  1670.             ctrl_bits = (ctrl_bits << 1) | 1;
  1671.             continue;
  1672.         }
  1673.  
  1674.         /* look for pattern if 2 or more characters
  1675.         remain in the input buffer  */
  1676.         in_idx = anchor;
  1677.         if((inbuff_end - in_idx) > 2)
  1678.         {
  1679.             /* locate offset of possible pattern
  1680.             in sliding dictionary  */
  1681.             hash = ((((in_idx[0] & 15) << 8) | in_idx[1]) ^
  1682.                 ((in_idx[0] >> 4) | (in_idx[2] << 4)))
  1683.                 & hash_len;
  1684.             pat_idx = hash_tbl[hash];
  1685.             hash_tbl[hash] = in_idx;
  1686.             /* compare characters if we're within 4098 bytes */
  1687.             if((gap = in_idx - pat_idx) <= 4098)
  1688.             {
  1689.                 while(in_idx < inbuff_end
  1690.                         && pat_idx < anchor && *pat_idx == *in_idx
  1691.                         && (in_idx - anchor) < 271)
  1692.                 {
  1693.                     in_idx++;
  1694.                     pat_idx++;
  1695.                 }
  1696.                 /* store pattern if it is more than 2 characters */
  1697.                 if((cnt = in_idx - anchor) > 2)
  1698.                 {
  1699.                     gap -= 3;
  1700.                     if(cnt <= 15) /* short pattern */
  1701.                     {
  1702.                         *out_idx++ = (cnt << 4) + (gap & 0x0F);
  1703.                         *out_idx++ = gap >> 4;
  1704.                     }
  1705.                     else          /* long pattern */
  1706.                     {
  1707.                         *out_idx++ = 32 + (gap & 0x0F);
  1708.                         *out_idx++ = gap >> 4;
  1709.                         *out_idx++ = cnt - 16;
  1710.                     }
  1711.                     ctrl_bits = (ctrl_bits << 1) | 1;
  1712.                     continue;
  1713.                 }
  1714.             }
  1715.         }
  1716.         /* can't compress this character
  1717.         so copy it to outbuff  */
  1718.         *out_idx++ = c;
  1719.         in_idx = ++anchor;
  1720.         ctrl_bits <<= 1;
  1721.     }
  1722.     /* save last load of control bits */
  1723.     ctrl_bits <<= (16 - ctrl_cnt);
  1724.     *ctrl_idx = ctrl_bits;
  1725.     /* and return size of compressed buffer */
  1726.     return out_idx - outbuff;
  1727. }
  1728.  
  1729. /*                                                 from C Users Journal 10/92
  1730.  * DECOMPRS.C - Ross Data Compression (RDC)
  1731.  *              decompress function
  1732.  *
  1733.  * Written by Ed Ross, 1/92
  1734.  *
  1735.  * decompress inbuff_len bytes of inbuff into outbuff.
  1736.  * return length of outbuff.                            */
  1737.  
  1738. //#include <string.h>
  1739.  
  1740. typedef unsigned char uchar;        /*  8 bits, unsigned  */
  1741. typedef unsigned int  uint;         /* 16 bits, unsigned  */
  1742.  
  1743. int rdc_decompress(uchar *inbuff, uint inbuff_len, uchar *outbuff)
  1744. {
  1745.     uint    ctrl_bits;
  1746.     uint    ctrl_mask = 0;
  1747.     uchar   *inbuff_idx = inbuff;
  1748.     uchar   *outbuff_idx = outbuff;
  1749.     uchar   *inbuff_end = inbuff + inbuff_len;
  1750.     uint    cmd;
  1751.     uint    cnt;
  1752.     uint    ofs;
  1753.     //uint    len;
  1754.  
  1755.     /* process each item in inbuff  */
  1756.     while(inbuff_idx < inbuff_end)
  1757.     {
  1758.         /* get new load of control bits if needed */
  1759.         if((ctrl_mask >>= 1) == 0)
  1760.         {
  1761.             ctrl_bits = *(uint *) inbuff_idx;
  1762.             inbuff_idx += 2;
  1763.             ctrl_mask = 0x8000;
  1764.         }
  1765.         /* just copy this char if control bit is zero */
  1766.         if((ctrl_bits & ctrl_mask) == 0)
  1767.         {
  1768.             *outbuff_idx++ = *inbuff_idx++;
  1769.             continue;
  1770.         }
  1771.         /* undo the compression code */
  1772.         cmd = (*inbuff_idx >> 4) & 0x0F;
  1773.         cnt = *inbuff_idx++ & 0x0F;
  1774.  
  1775.         switch(cmd)
  1776.         {
  1777.             case 0:                 /* short rle */
  1778.             cnt += 3;
  1779.             memset(outbuff_idx, *inbuff_idx++, cnt);
  1780.             outbuff_idx += cnt;
  1781.             break;
  1782.             case 1:                 /* long rle */
  1783.             cnt += (*inbuff_idx++ << 4);
  1784.             cnt += 19;
  1785.             memset(outbuff_idx, *inbuff_idx++, cnt);
  1786.             outbuff_idx += cnt;
  1787.             break;
  1788.             case 2:                 /* long pattern */
  1789.             ofs = cnt + 3;
  1790.             ofs += (*inbuff_idx++ << 4);
  1791.             cnt = *inbuff_idx++;
  1792.             cnt += 16;
  1793.             memcpy(outbuff_idx, outbuff_idx - ofs, cnt);
  1794.             outbuff_idx += cnt;
  1795.             break;
  1796.             default:                /* short pattern */
  1797.             ofs = cnt + 3;
  1798.             ofs += (*inbuff_idx++ << 4);
  1799.             memcpy(outbuff_idx, outbuff_idx - ofs, cmd);
  1800.             outbuff_idx += cmd;
  1801.             break;
  1802.         }
  1803.     }
  1804.     /* return length of decompressed buffer */
  1805.     return outbuff_idx - outbuff;
  1806. }